package vcp.server.requesthandler;

import java.util.List;

import ocsf.server.ConnectionToClient;
import vcp.client.forms.PeriodicForm;
import vcp.client.reports.ComplaintsReport;
import vcp.client.reports.EmptyReport;
import vcp.client.reports.NonWorkingLotsReport;
import vcp.client.reports.ReportAbstract;
import vcp.client.reports.SubscriptionsReport;
import vcp.client.request.PeriodicReportRetrieveRequest;
import vcp.client.request.response.ResponseRequest;
import vcp.entity.Complaint;
import vcp.entity.ComplaintHistory;
import vcp.entity.Customer;
import vcp.entity.Lot;
import vcp.entity.Subscription;
import vcp.entity.SubscriptionHistory;
import vcp.server.DAO.ComplaintDAO;
import vcp.server.DAO.ComplaintHistoryDAO;
import vcp.server.DAO.CustomerDAO;
import vcp.server.DAO.LotDAO;
import vcp.server.DAO.SubscriptionDAO;
import vcp.server.DAO.SubscriptionHistoryDAO;
import vcp.server.interfaces.IServer;

/**
 * 
 * @author VCP team
 *         <p>
 *         class handles retrieving periodic reports from client
 *         </p>
 */
public class PeriodicReportRetrieveRequestHandler extends RequestHandler <PeriodicReportRetrieveRequest>
{
	/**
	 * class constructor
	 * 
	 * @param server
	 */
	public PeriodicReportRetrieveRequestHandler ( IServer server )
	{
		super(server);
	}

	@Override
	public void execute ( PeriodicReportRetrieveRequest request, ConnectionToClient client )
	{
		ResponseRequest response = new ResponseRequest(request.getRequestID(), null);
		ReportAbstract report = new EmptyReport();

		switch ( request.getForm().getReportType() )
		{
			case COMPLAINTS:
				report = this.retrieveComplaints(request.getForm());
				break;
			case NON_WORKING_LOT:
				report = this.retrieveNonWorkingLots(request.getForm());
				break;
			case SUBSCRIPTION:
				report = this.retrieveSubscriptions(request.getForm());
				break;
			default:
				break;
		}

		response.setData(report);
		this.sendResponse(response, client);
	}

	// ****************************************************************************************************************************
	// Private methods
	// ****************************************************************************************************************************
	/**
	 * @param periodicForm
	 *            containing dates period
	 * @return SubscriptionsReports on success, otherwise EmptyReport
	 */
	private ReportAbstract retrieveSubscriptions ( PeriodicForm periodicForm )
	{
		// DAO's which be used for retrieval
		SubscriptionDAO subscriptionDAO = new SubscriptionDAO();
		SubscriptionHistoryDAO subscriptionHistoryDAO = new SubscriptionHistoryDAO();
		CustomerDAO customerDAO = new CustomerDAO();

		// generated reports
		SubscriptionsReport subscriptionsReport = new SubscriptionsReport();

		// search for all current subscriptions
		List <Subscription> subscriptions = subscriptionDAO.findAllSubscriptionsByDatesPeriod(periodicForm.getStartDate(), periodicForm.getEndDate(), periodicForm.getSiteEnum());
		for ( Subscription subscription : subscriptions )
		{
			Customer customer = customerDAO.findByID(subscription.getCustomerID());
			subscriptionsReport.add(subscription, customer);
		}

		// search for all history subscriptions
		List <SubscriptionHistory> subscriptionsHistory = subscriptionHistoryDAO.findAllSubscriptionsHistoryByDatesPeriodForSite(periodicForm.getStartDate(), periodicForm.getEndDate(), periodicForm.getSiteEnum());
		for ( SubscriptionHistory subscriptionHistory : subscriptionsHistory )
		{
			Customer customer = customerDAO.findByID(subscriptionHistory.getCustomerID());
			subscriptionsReport.add(subscriptionHistory, customer);
		}

		return subscriptionsReport.hasData()
											? subscriptionsReport
											: new EmptyReport();
	}

	/**
	 * @param periodicForm
	 *            containing dates period
	 * @return NonWorkingLotsReport on success, otherwise EmptyReport
	 */
	private ReportAbstract retrieveNonWorkingLots ( PeriodicForm periodicForm )
	{
		LotDAO lotDAO = new LotDAO();

		NonWorkingLotsReport nonWorkingLotsReport = new NonWorkingLotsReport();

		List <Lot> lots = lotDAO.findAllBrokenByDatePeriod(periodicForm.getStartDate(), periodicForm.getEndDate(), periodicForm.getSiteEnum());
		for ( Lot lot : lots )
		{
			nonWorkingLotsReport.add(lot);
		}

		return nonWorkingLotsReport.hasData()
												? nonWorkingLotsReport
												: new EmptyReport();
	}

	/**
	 * @param periodicForm
	 *            containing dates period
	 * @return ComplaintsReport on success, otherwise EmptyReport
	 */
	private ReportAbstract retrieveComplaints ( PeriodicForm periodicForm )
	{
		ComplaintDAO complaintDAO = new ComplaintDAO();
		ComplaintHistoryDAO complaintHistoryDAO = new ComplaintHistoryDAO();
		CustomerDAO customerDAO = new CustomerDAO();

		ComplaintsReport complaintsReport = new ComplaintsReport();

		List <Complaint> complaints = complaintDAO.findAllComplaintsFromDate(periodicForm.getStartDate(), periodicForm.getSiteEnum());
		for ( Complaint complaint : complaints )
		{
			Customer customer = customerDAO.findByID(complaint.getCustomerID());

			ComplaintHistory complaintHistory = null;
			if ( complaint.isHistory() )
			{
				complaintHistory = complaintHistoryDAO.findComplaintByIDTillDate(complaint.getID(), periodicForm.getEndDate(), periodicForm.getSiteEnum());
			}

			complaintsReport.add(complaint, complaintHistory, customer);
		}

		return complaintsReport.hasData()
											? complaintsReport
											: new EmptyReport();
	}

}
